<script setup lang="ts">
import { ElSelect } from 'element-plus'
import { getOptions } from '../../../utils/index.ts'
import type { FormItemTool } from '../../../types/index.ts'

type IProps = {
  item: FormItemTool<'select'> & { config?: { options?: any[] } }
  allDisabled: boolean
  isEditByRow: boolean
  data: Record<string, any>
}
const emit = defineEmits(['update:data', 'specific'])
const props = withDefaults(defineProps<IProps>(), {
  isEditByRow: true,
})
const { item, allDisabled, isEditByRow } = toRefs(props)
const value = defineModel<any>('value')
const elRef = useTemplateRef('elRef')
const getRef = () => {
  return elRef.value
}
const labelKey = computed(() => item.value?.config?.props?.label || 'label')
const valueKey = computed(() => item.value?.config?.props?.value || 'value')

const nameKey = computed(() => {
  if(item.value.config?.mapping) {
    return item.value.config.mapping['label']
  }
  return undefined
})
const name = computed(() => {
  if(nameKey.value) {
    return props.data[nameKey.value]
  }
  return undefined
})
const temporaryOptions = computed(() => {
  if(name.value) {
    return [{ [labelKey.value]: name.value, [valueKey.value]: value.value }]
  }
  return []
})
const optionsScoped = ref([])
const options = computed(() => {
  if (item.value?.config?.options || item.value.options) {
    const arr = getOptions(item.value)
    return arr.length > 0 ? arr : temporaryOptions.value
  }
  return optionsScoped.value.length > 0 ? optionsScoped.value : temporaryOptions.value
})
const currentOption = computed(() => {
  if(!Array.isArray(value.value)) {
    let option = options.value.find((item) => item[valueKey.value] === value.value)
    if(!option) option = { [labelKey.value]: value.value, [valueKey.value]: value.value }
    return option
  } 
  return value.value.map((val: any) => {
    let option = options.value.find((item) => item[valueKey.value] === val)
    if(!option) option = { [labelKey.value]: val, [valueKey.value]: val }
    return option
  })
})
function updateModelValue(val: any) {
  nextTick(() => {
    nextTick(() => {
      if(nameKey.value) emit('update:data', {...props.data, [nameKey.value]: currentOption.value?.[labelKey.value] })
    })
  })
  value.value = val
}
function remoteMethod(query: string) {
  item.value?.config?.remoteMethod?.(query, optionsScoped)
}
if(value) {
  item.value?.config?.remoteMethod?.(value.value, optionsScoped)
}
const label = ref('')
watchEffect(() => {
  if(!item.value.field) return
  const optionAt = currentOption.value
  label.value = Array.isArray(optionAt)  ? optionAt.map((item) => item[labelKey.value || 'label']).join(',')  : optionAt[labelKey.value || 'label']
  emit('specific', { optionAt, value: value.value, label: label.value, options: options.value as any })
})
const attrs = useAttrs()
defineExpose({
  getRef,
})
</script>
<template>
  <span class="w-full">
    <el-select v-if="isEditByRow"
      clearable
      ref="elRef"
      :disabled="allDisabled"
      :modelValue="value"
      @update:modelValue="updateModelValue"
      v-bind="{...item.config, ...attrs}"
      :remote-method="remoteMethod"
      v-on="item.eventFunction || {}"
    >
      <el-option
        v-for="option in options"
        v-bind="option"
        :value="option[valueKey]"
        :label="option[labelKey]"
        :key="option.key ?? option[valueKey]"
        v-on="item.optionFunction || {}"
      >
      </el-option>
      <template v-for="slotName in item.slotNames" #[slotName]="slotData">
        <slot :name="slotName" :slotData="slotData"> </slot>
      </template>
    </el-select>
    <span v-else> {{ label }} </span>
  </span>
</template>

<style scoped lang="scss">
:deep(.el-select) {
    width: 100%;
  }
</style>
